package com.explorx.sns.puma.im.core.chat.impl;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.explorex.puma.common.enums.VisibleEnum;
import com.explorex.puma.common.utils.SnowflakeIdWorker;
import com.explorx.sns.puma.im.core.chat.ConversationService;
import com.explorx.sns.puma.im.core.chat.MessageService;
import com.explorx.sns.puma.im.core.chat.UserInfoDomainService;
import com.explorx.sns.puma.im.core.chat.consts.MessageStatusEnum;
import com.explorx.sns.puma.im.core.chat.consts.MessageTypeEnum;
import com.explorx.sns.puma.im.core.chat.consts.StatusEnum;
import com.explorx.sns.puma.im.core.chat.model.ConversationModel;
import com.explorx.sns.puma.im.core.chat.model.CreateConvModel;
import com.explorx.sns.puma.im.core.chat.model.MessageModel;
import com.explorx.sns.puma.im.core.chat.model.UserInfoModel;
import com.explorx.sns.puma.im.core.common.utils.DateUtils;
import com.explorx.sns.puma.im.core.dal.dao.ConversationEntityMapper;
import com.explorx.sns.puma.im.core.dal.entity.ConversationEntity;
import com.explorx.sns.puma.im.core.dal.entity.ConversationEntityExample;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ConversationServiceImpl implements ConversationService {

    @Resource
    private ConversationEntityMapper conversationEntityMapper;

    @Resource
    private UserInfoDomainService userInfoDomainService;

    @Resource
    private MessageService messageService;


    @Override
    public List<ConversationModel> getUserConversation(Long userId, Date cidUpdateTime, int pageId, int pageSize) {
        ConversationEntityExample example = new ConversationEntityExample();
        example.createCriteria()
                .andVisibleEqualTo(true)
                .andUserIdEqualTo(userId)
                .andStatusEqualTo((byte) StatusEnum.OK.getValue())
                .andUpdateTimeLessThan(cidUpdateTime);
        //todo 分页
        final List<ConversationEntity> conversationEntities = conversationEntityMapper.selectByExample(example);

        if (CollectionUtils.isEmpty(conversationEntities)) {
            return Collections.emptyList();
        }
        // 排序，置顶top rank 优先，其次最后一条消息时间

        conversationEntities.sort((o1, o2) -> o1.getTopRank()-o2.getTopRank() !=0
                ? o2.getTopRank()-o1.getTopRank()
                : o2.getUpdateTime().compareTo(o1.getUpdateTime()));

        final List<Long> partnerIds = conversationEntities.stream()
                .map(ConversationEntity::getPartnerId)
                .collect(Collectors.toList());
        final List<Long> messageIds = conversationEntities.stream().map(ConversationEntity::getLastMessageId)
                .collect(Collectors.toList());

        final List<UserInfoModel> usersInfo = userInfoDomainService.getUsersInfo(partnerIds);
        final List<MessageModel> messageModels = messageService.batchGetMessageByIds(messageIds);
        //
        List<ConversationModel> result = Lists.newArrayList();
        for (ConversationEntity entity : conversationEntities) {
            final UserInfoModel userInfoModel = usersInfo.stream().filter(ele -> ele.getUserId()
                    .equals(entity.getPartnerId())).findAny().get();
            final MessageModel messageModel = messageModels.stream()
                    .filter(ele -> ele.getMessageId().equals(entity.getLastMessageId())).findAny().get();
            assert userInfoModel != null;
            assert messageModel != null;
            ConversationModel conversationModel = ConversationModel
                    .builder().cid(entity.getCid())
                    .convUrl(userInfoModel.getAvatar())
                    .convName(Optional.ofNullable(entity.getPartnerAlias())
                            .orElse(userInfoModel.getUserName()))
                    .mute(entity.getMute())
                    .partnerId(entity.getPartnerId())
                    .senderId(entity.getUserId())
                    .lastMsg(buildMsgPreview(messageModel))
                    .lastMsgTime(DateUtils.buildMsgDateOrTime(new Date(messageModel.getUpdateTime())))
                    .redPointCnt(entity.getRedPoint())
                    .topRank(entity.getTopRank()).build();
            result.add(conversationModel);
        }
        return result;
    }


    private String buildMsgPreview(MessageModel messageModel) {
        if (messageModel.getStatus() == MessageStatusEnum.Revoke.getStatus()) {
            return MessageStatusEnum.Revoke.getDesc();
        }
        final MessageTypeEnum messageTypeEnum = MessageTypeEnum.findByValue(messageModel.getMessageType());
        final JSON parse = JSONUtil.parse(messageModel.getMessageContent());
        switch (messageTypeEnum) {
            case TEXT:
                return (String) parse.getByPath("text");
            default:
                return messageModel.getMessageContent();
        }
    }

    @Override
    public List<MessageModel> getConversationMessage(Long uid, Long cid) {
        return messageService.getConversationMessage(uid,cid);
    }

    @Override
    public ConversationModel getUserConvByUserIdAndCid(Long userId, Long cid) {
        ConversationEntityExample example = new ConversationEntityExample();
        example.createCriteria()
                .andUserIdEqualTo(userId)
                .andStatusEqualTo((byte) StatusEnum.OK.getValue())
                .andCidEqualTo(cid);
        //todo 分页
        final List<ConversationEntity> conversationEntities = conversationEntityMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(conversationEntities)) {
            final ConversationEntity entity = conversationEntities.get(0);
            return ConversationModel
                    .builder().cid(entity.getCid())
                    .mute(entity.getMute())
                    .redPointCnt(entity.getRedPoint())
                    .topRank(entity.getTopRank()).build();
        }
        return null;
    }

    @Override
    public ConversationModel getUserConvByPair(Long fromUserId, Long toUserId) {
        ConversationEntityExample example = new ConversationEntityExample();
        example.createCriteria()
                .andUserIdEqualTo(fromUserId)
                .andStatusEqualTo((byte) StatusEnum.OK.getValue())
                .andPartnerIdEqualTo(toUserId);
        final List<ConversationEntity> conversationEntities = conversationEntityMapper.selectByExample(example);
        // 从来没有聊天过
        if(CollectionUtils.isEmpty(conversationEntities)){
            return ConversationModel
                    .builder().cid(0)
                    .mute(false)
                    .senderId(fromUserId).partnerId(toUserId)
                    .redPointCnt(0)
                    .topRank(0).build();
        }
        final ConversationEntity entity = conversationEntities.get(0);
        return ConversationModel
                .builder().cid(entity.getCid())
                .mute(entity.getMute())
                .senderId(fromUserId).partnerId(toUserId)
                .redPointCnt(entity.getRedPoint())
                .topRank(entity.getTopRank()).build();
    }

    @Override
    public boolean updateLastMsg(MessageModel messageModel) {
        ConversationEntity entity = new ConversationEntity();
        entity.setLastMessageId(messageModel.getMessageId());
        entity.setUpdateTime(new Date());
        entity.setVisible(true);
        entity.setStatus((byte) StatusEnum.OK.getValue());
        // 双方的会话都会被设置为可见
        ConversationEntityExample example = new ConversationEntityExample();
        example.createCriteria()
                .andCidEqualTo(messageModel.getCid())
                .andUserIdEqualTo(messageModel.getSenderId());
        return conversationEntityMapper.updateByExampleSelective(entity, example) > 0;
    }

    @Override
    public Long createConversation(CreateConvModel convModel) {
        final Long cid = SnowflakeIdWorker.nextId();
        convModel.setCid(cid);
        ConversationEntity entity = new ConversationEntity();
        entity.setPartnerId(convModel.getPartnerId());
        entity.setCid(cid);
        entity.setUserId(convModel.getSenderId());
        entity.setRedPoint(1);
        entity.setMute(false);
        entity.setType(convModel.getConvType());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        entity.setVisible(convModel.getVisible()==VisibleEnum.PUBLIC.getValue());
        entity.setStatus((byte) StatusEnum.OK.getValue());
        final int insert = conversationEntityMapper.insert(entity);
        return cid;
    }

    @Override
    public boolean deleteConv(Long userId, Long cid) {
        ConversationEntity conversationEntity=new ConversationEntity();
        conversationEntity.setVisible(false);
        ConversationEntityExample example=new ConversationEntityExample();
        example.createCriteria().andCidEqualTo(cid).andUserIdEqualTo(userId);
        return conversationEntityMapper.updateByExampleSelective(conversationEntity, example)>0;
    }

    @Override
    public int topRank(Long userId, Long cid, boolean top) {
        ConversationEntity conversationEntity=new ConversationEntity();
        int topRank= top ? (int) Instant.now().toEpochMilli(): 0;
        conversationEntity.setTopRank(topRank);
        ConversationEntityExample example=new ConversationEntityExample();
        example.createCriteria().andCidEqualTo(cid).andUserIdEqualTo(userId);
        if (conversationEntityMapper.updateByExampleSelective(conversationEntity, example)>0) {
            return  topRank;
        }
        return  0;
    }
}
